import socket, traceback

host = ''  # 绑定所有可用网络接口
port = 51423  # 服务监听端口

# 创建TCP socket对象
# AF_INET: IPv4地址族
# SOCK_STREAM: TCP协议类型
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 设置socket选项 SO_REUSEADDR:
# 作用：允许在服务器重启后立即重用相同端口（避免"Address already in use"错误）
# 参数说明：
#   SOL_SOCKET: 操作socket层级的选项
#   SO_REUSEADDR: 启用地址重用
#   1: 启用选项（True）
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# 绑定socket到指定主机和端口
s.bind((host, port))

# 开始监听，参数1表示最多允许1个连接在队列中等待接受
s.listen(1)

# 主服务循环
while 1:
    try:
        # accept()函数：
        # 作用：阻塞等待客户端连接，当连接到达时返回：
        #   clientsock: 新socket对象（用于与客户端通信）
        #   clientaddr: 客户端地址(IP, port)元组
        clientsock, clientaddr = s.accept()
    except KeyboardInterrupt:
        # 捕获Ctrl+C中断信号，直接抛出终止程序
        raise
    except:
        # 捕获其他所有异常，打印堆栈跟踪后继续运行
        traceback.print_exc()
        continue
    
    # 客户端连接处理逻辑
    try:
        print('Got connection from', clientsock.getpeername())
        while True:
            # 接收客户端数据（最大4096字节）
            data = clientsock.recv(4096)
            
            # 当接收到空数据时（客户端关闭连接）
            if not len(data):
                break
            
            # 回显数据给客户端（需要先解码字符串再发送）
            clientsock.sendall(data)
    
    # 异常处理区块：
    except (KeyboardInterrupt, SystemExit):
        # 捕获中断或系统退出异常，直接抛出终止程序
        raise
    except:
        # 捕获其他所有异常，打印堆栈跟踪但不终止程序
        traceback.print_exc()
    
    # 客户端连接清理
    try:
        clientsock.close()  # 关闭客户端socket
    except KeyboardInterrupt:
        raise
    except:
        traceback.print_exc()